package com.fpc.util.fileUtil;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.badger.generator.entity.BuildResult;
import com.fpc.util.FilePath;


/* https://www.jb51.net/article/228548.htm
 * https://www.cnblogs.com/hkgov/p/14707726.html
 * 
 * 方法
 *  使用 BufferedReader 类
 *	使用 Scanner 类 ，可以使用他的读取文本，但是不推荐使用他的正则表达式，可以获取指定类型（优势）
 *	使用 字节流 字符流 类
 *	使用文件阅读器类
 *	读取列表中的整个文件
 *	将文本文件读取为字符串
 * 
 * 
 * 工具
 *  Scanner(Java 1.5以上) 按行读数据及String、Int类型，正则表达式等按分隔符读数据。
 *	Files.lines, 返回Stream(Java 8) 流式数据处理，按行读取
 *	Files.readAllLines, 返回List(Java 8)
 *	Files.readString, 读取String(Java 11), 文件最大 2G.
 *	Files.readAllBytes, 读取byte[](Java 7), 文件最大 2G.
 *	BufferedReader, 经典方式 (Java 1.1 -> forever) 以行为单位读取文件 
 */
public class ReadFromFile2 {
	public static void main(String[] args) throws Exception
    {
		BuildResult fdas=new BuildResult();
		 SerializeWriter out = new SerializeWriter();
		
		
		
		String path=FilePath.getPackagePath(BuildResult.class)+"BuildResult.java";
		//D:/badger-generator/badger-generator/target/classes/com/badger/generator/entity/BuildResult.class
		path=path.replace("/target/classes", "/src/main/java");
		readFileByBytes(path);
    }
	
	/**
     * Scanner(Java 1.5以上)  ,不推荐使用他的正则表达式， 使用正则表达式分隔符，会被替换为空，局限性大，
	 * @throws FileNotFoundException 
     */
    public static void readFileByBytes(String fileName) throws FileNotFoundException {
    	 
    	   try (Scanner sc = new Scanner(new FileReader(fileName))) {
    	      while (sc.hasNextLine()) {  //按行读取字符串
    	         String line = sc.nextLine();
    	         System.out.println(line);
    	      }
    	   }
    	 
    	   try (Scanner sc = new Scanner(new FileReader(fileName))) {
    	      sc.useDelimiter("\\|");  //分隔符
    	      while (sc.hasNext()) {   //按分隔符读取字符串
    	         String str = sc.next();
    	         System.out.println(str);
    	      }
    	   }
    	 
    	   //sc.hasNextInt() 、hasNextFloat() 、基础数据类型等等等等。
    	   //文件内容：1|2
    	   try (Scanner sc = new Scanner(new FileReader(fileName))) {
    	      sc.useDelimiter("\\|");  //分隔符
    	      
    	      while (sc.hasNextInt()) {   //按分隔符读取Int
    	          int intValue = sc.nextInt();
    	         System.out.println(intValue);
    	      }
    	   }
    	   
    	   
    	   try (Scanner sc = new Scanner(new FileReader(fileName))) {
     	     Pattern pattern = Pattern.compile("\\/\\*\\*(\\n.*){0,4}\\n.*private.*;$");
     		//Matcher matcher = pattern.matcher(INPUT);
     		//matcher.find()//true, false
        	//matcher.reset();
     	      while ( sc.hasNext(pattern)) {   
     	          String intValue = sc.next();
     	         System.out.println(intValue);
     	      }
     	   }
    
    
    }
    
    /**
     * 2.Files.lines (Java 8)
     * 如果你是需要按行去处理数据文件的内容，这种方式是我推荐大家去使用的一种方式，
     * 代码简洁，使用java 8的Stream流将文件读取与文件处理有机融合。
     * @throws IOException 
     */
    public static void testReadFile(String fileName) throws IOException {
    	 
    	   // 读取文件内容到Stream流中，按行读取
    	   Stream<String> lines = Files.lines(Paths.get(fileName));
    	 
    	   //1  随机行顺序进行数据处理
    	   lines.forEach(ele -> {
    	      System.out.println(ele);
    	   });
    	  //2   按文件行顺序进行处理
    	   lines.forEachOrdered(System.out::println);
    	   
    	   //3 也可以把Stream转换成List,但是要注意这意味着你要将所有的数据一次性加载到内存，要注意java.lang.OutOfMemoryError
    	   List<String> collect = lines.collect(Collectors.toList());//这个时候也是个有序集合
    }
    /**
     * 3.Files.readAllLines（java8）
     * 从文件中读取所有行。
     * 此方法可确保在读取所有字节或抛出 I/O 错误或其他运行时异常时关闭文件。
     * 使用指定的字符集将文件中的字节解码为字符。 
     */
    void testReadFile3(String fileName) throws IOException {
    	 
    	   // 转换成List<String>, 要注意java.lang.OutOfMemoryError: Java heap space
    	   List<String> lines = Files.readAllLines(Paths.get(fileName),StandardCharsets.UTF_8);
    	   lines.forEach(System.out::println);
    }
    	
    /**
     * 4.Files.readString(JDK 11)
     */
    void testReadFile4(String fileName) throws IOException {
     
       // java 11 开始提供的方法，读取文件不能超过2G，与你的内存息息相关
       //String s = Files.readString(Paths.get(fileName));
    }
    
    /**
     * 5.Files.readAllBytes()  将文本文件读取为字符串
     * 如果你没有JDK11（readAllBytes()始于JDK7）,
     * 仍然想一次性的快速读取一个文件的内容转为String，该怎么办？
     * 先将数据读取为二进制数组，然后转换成String内容。
     * 这种方法适合在没有JDK11的请开给你下，快速读取小文本文件。
     */
    void testReadFile5( String fileName) throws IOException {
    	   //如果是JDK11用上面的方法，如果不是用这个方法也很容易
    	   byte[] bytes = Files.readAllBytes(Paths.get(fileName));
    	   String content = new String(bytes, StandardCharsets.UTF_8);
    	   System.out.println(content);
   }
    
    /**
     * 6.经典管道流的方式
     * BufferedReader
     * 此方法从字符输入流中读取文本。
     * 它确实缓冲以有效读取字符、数组和行。
     * 可以指定缓冲区大小，也可以使用默认大小。
     */
    void testReadFile6() throws IOException {
    	   String fileName = "D:\\data\\test\\newFile3.txt";
    	 
    	   // 带缓冲的流读取，默认缓冲区8k
    	   try (BufferedReader br = new BufferedReader(new FileReader(fileName))){
    	      String line;
    	      while ((line = br.readLine()) != null) {
    	         System.out.println(line);
    	      }
    	   }
    	 
    	   //java 8中这样写也可以
    	   try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))){
    	      String line;
    	      while ((line = br.readLine()) != null) {
    	         System.out.println(line);
    	      }
    	   }
    	}
    
    
}
